//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_SERIALIO_H__
#define __ELASTOS_SERIALIO_H__

// ====================================================================
//
//      serctrl.h
//
//      Device I/O
//
// ====================================================================

// This file contains the user-level visible I/O interfaces

#ifdef __cplusplus
extern "C" {
#endif

// This file contains all of the 'key' values used by all I/O components.
// It is placed in this single repository to make it easy to reduce conflicts.

// ======== 0x0100 Serial ====================================================
// Get/Set configuration 'key' values for low-level serial I/O

#define IO_GET_CONFIG_SERIAL_TIMEOUT               0x0101
#define IO_GET_CONFIG_SERIAL_INFO                  0x0102
#define IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN          0x0103
#define IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH          0x0104
#define IO_GET_CONFIG_SERIAL_INPUT_FLUSH           0x0105
#define IO_GET_CONFIG_SERIAL_ABORT                 0x0106
#define IO_GET_CONFIG_SERIAL_BUFFER_INFO           0x0107
#define IO_GET_CONFIG_SERIAL_FLOW_CONTROL_METHOD   0x0108
#define IO_GET_CONFIG_SERIAL_WAITEVENT_MASK        0x0109
#define IO_GET_CONFIG_SERIAL_MODEM_STATUS          0x010A

#define IO_SET_CONFIG_SERIAL_OPEN                  0x0171
#define IO_SET_CONFIG_SERIAL_CLOSE                 0x0172
#define IO_SET_CONFIG_SERIAL_TIMEOUT               0x0173
#define IO_SET_CONFIG_SERIAL_INFO                  0x0174
#define IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE   0x0175
#define IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG        0x0176
#define IO_SET_CONFIG_SERIAL_FLOW_CONTROL_METHOD   0x0177
#define IO_SET_CONFIG_SERIAL_FLOW_CONTROL_FORCE    0x0178
#define IO_SET_CONFIG_SERIAL_STATUS_CALLBACK       0x0179
#define IO_SET_CONFIG_SERIAL_HW_BREAK              0x017A
#define IO_SET_CONFIG_SERIAL_BUFFER_INFO           0x017B
#define IO_SET_CONFIG_SERIAL_WAITEVENT_MASK        0x017C

// Compatibility values. Use of these is deprecated, the generic symbols
// should be used instead.
#define IO_GET_CONFIG_SERIAL_READ_BLOCKING   IO_GET_CONFIG_READ_BLOCKING
#define IO_GET_CONFIG_SERIAL_WRITE_BLOCKING  IO_GET_CONFIG_WRITE_BLOCKING
#define IO_SET_CONFIG_SERIAL_READ_BLOCKING   IO_SET_CONFIG_READ_BLOCKING
#define IO_SET_CONFIG_SERIAL_WRITE_BLOCKING  IO_SET_CONFIG_WRITE_BLOCKING

// ======== 0x1000 Generic ===================================================
// Get/Set configuration 'key' values that can apply to more than one
// class of device.

#define IO_GET_CONFIG_READ_BLOCKING               0x1001
#define IO_GET_CONFIG_WRITE_BLOCKING              0x1002

#define IO_SET_CONFIG_READ_BLOCKING               0x1081
#define IO_SET_CONFIG_WRITE_BLOCKING              0x1082

// Supported baud rates
typedef enum {
    NUM_SERIAL_BAUD_50 = 1,
    NUM_SERIAL_BAUD_75,
    NUM_SERIAL_BAUD_110,
    NUM_SERIAL_BAUD_134_5,
    NUM_SERIAL_BAUD_150,
    NUM_SERIAL_BAUD_200,
    NUM_SERIAL_BAUD_300,
    NUM_SERIAL_BAUD_600,
    NUM_SERIAL_BAUD_1200,
    NUM_SERIAL_BAUD_1800,
    NUM_SERIAL_BAUD_2400,
    NUM_SERIAL_BAUD_3600,
    NUM_SERIAL_BAUD_4800,
    NUM_SERIAL_BAUD_7200,
    NUM_SERIAL_BAUD_9600,
    NUM_SERIAL_BAUD_14400,
    NUM_SERIAL_BAUD_19200,
    NUM_SERIAL_BAUD_38400,
    NUM_SERIAL_BAUD_57600,
    NUM_SERIAL_BAUD_115200,
    NUM_SERIAL_BAUD_230400,
    NUM_SERIAL_BAUD_380400,
    NUM_SERIAL_BAUD_460800,
    NUM_SERIAL_BAUD_921600,
} serial_baud_rate_t;
#define NUM_SERIAL_BAUD_MIN NUM_SERIAL_BAUD_50
#define NUM_SERIAL_BAUD_MAX NUM_SERIAL_BAUD_921600

// Note: two levels of macro are required to get proper expansion.
#define _SERIAL_BAUD_RATE(n) NUM_SERIAL_BAUD_##n
#define SERIAL_BAUD_RATE(n) _SERIAL_BAUD_RATE(n)

// Stop bit selections
typedef enum {
    NUM_SERIAL_STOP_1 = 1,
    NUM_SERIAL_STOP_1_5,
    NUM_SERIAL_STOP_2
} serial_stop_bits_t;

// Parity modes
typedef enum {
    NUM_SERIAL_PARITY_NONE = 0,
    NUM_SERIAL_PARITY_EVEN,
    NUM_SERIAL_PARITY_ODD,
    NUM_SERIAL_PARITY_MARK,
    NUM_SERIAL_PARITY_SPACE
} serial_parity_t;

// Word length
typedef enum {
    NUM_SERIAL_WORD_LENGTH_5 = 5,
    NUM_SERIAL_WORD_LENGTH_6,
    NUM_SERIAL_WORD_LENGTH_7,
    NUM_SERIAL_WORD_LENGTH_8
} serial_word_length_t;

typedef struct {
    serial_baud_rate_t      baud;
    serial_stop_bits_t      stop;
    serial_parity_t         parity;
    serial_word_length_t    word_length;
    UINT32                  flags;
} SERIAL_INFO;

typedef SERIAL_INFO     SerialInfo;

typedef struct {
    DWORD ReadIntervalTimeout;
    DWORD ReadTotalTimeoutMultiplier;
    DWORD ReadTotalTimeoutConstant;
    DWORD WriteTotalTimeoutMultiplier;
    DWORD WriteTotalTimeoutConstant;
} SERIAL_TIMEOUTS;

// SERIAL_INFO flags

#define NUM_SERIAL_FLOW_NONE              (0)
// receive flow control, send xon/xoff when necessary:
#define NUM_SERIAL_FLOW_XONXOFF_RX        (1<<0)
// transmit flow control, act on received xon/xoff:
#define NUM_SERIAL_FLOW_XONXOFF_TX        (1<<1)
// receive flow control, send RTS when necessary:
#define NUM_SERIAL_FLOW_RTSCTS_RX         (1<<2)
// transmit flow control, act when not CTS:
// the CTS (clear-to-send) signal is monitored for output flow control. If this
// member is TRUE and CTS is turned off, output is suspended until CTS is
// sent again
#define NUM_SERIAL_FLOW_RTSCTS_TX         (1<<3)
// receive flow control, send DTR when necessary:
#define NUM_SERIAL_FLOW_DSRDTR_RX         (1<<4)
// transmit flow control, act when not DSR:
// the DSR (data-set-ready) signal is monitored for output flow control. If
// this member is TRUE and DSR is turned off, output is suspended until DSR
// is sent again
#define NUM_SERIAL_FLOW_DSRDTR_TX         (1<<5)

// arguments for IO_SET_CONFIG_SERIAL_FLOW_CONTROL_FORCE
#define NUM_SERIAL_FLOW_THROTTLE_RX       0
#define NUM_SERIAL_FLOW_RESTART_RX        1
#define NUM_SERIAL_FLOW_THROTTLE_TX       2
#define NUM_SERIAL_FLOW_RESTART_TX        3

// arguments for IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE
#define NUM_SERIAL_FLOW_HW_THROTTLE       0
#define NUM_SERIAL_FLOW_HW_UNTHROTTLE     1

#define DAT_IO_SERIAL_FLOW_CONTROL_XON_CHAR  17
#define DAT_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR 19

// arguments for  IO_GET_CONFIG_SERIAL_WAITEVENT_MASK\IO_SET_CONFIG_SERIAL_WAITEVENT_MASK
#define NUM_EV_RXCHAR           0x0001  // Any Character received
#define NUM_EV_RXFLAG           0x0002  // Received certain character(no supported currently)
#define NUM_EV_TXEMPTY          0x0004  // Transmitt Queue Empty
#define NUM_EV_CTS              0x0008  // CTS changed state
#define NUM_EV_DSR              0x0010  // DSR changed state
#define NUM_EV_RLSD             0x0020  // RLSD changed state(no supported currently)
#define NUM_EV_BREAK            0x0040  // BREAK received
#define NUM_EV_ERR              0x0080  // Line status error occurred
#define NUM_EV_RING             0x0100  // Ring signal detected
#define NUM_EV_PERR             0x0200  // Printer error occured(no supported currently)

// modem states flags
#define NUM_CTS_ON              0x0010  // The CTS (clear-to-send) signal is on.
#define NUM_DSR_ON              0x0020  // The DSR (data-set-ready) signal is on.
#define NUM_RING_ON             0x0040  // The ring indicator signal is on.
#define NUM_RLSD_ON             0x0080  // The RLSD (receive-line-signal-detect) signal is on.

typedef struct {
    UINT32 rx_bufsize;
    UINT32 rx_count;
    UINT32 tx_bufsize;
    UINT32 tx_count;
} serial_buf_info_t;

#define NUM_SERIAL_STATUS_FLOW           0
#define NUM_SERIAL_STATUS_BREAK          1
#define NUM_SERIAL_STATUS_FRAMEERR       2
#define NUM_SERIAL_STATUS_PARITYERR      3
#define NUM_SERIAL_STATUS_OVERRUNERR     4
#define NUM_SERIAL_STATUS_CARRIERDETECT  5
#define NUM_SERIAL_STATUS_RINGINDICATOR  6

typedef struct {
    UINT32 which;        // one of NUM_SERIAL_STATUS_* above
    UINT32 value;        // and its value
} serial_line_status_t;

typedef void
    (*serial_line_status_callback_fn_t)(serial_line_status_t *s, UINT32 priv);

typedef struct {
    serial_line_status_callback_fn_t fn;
    UINT32 priv;
} serial_line_status_callback_t;

// Default configuration
#define SERIAL_BAUD_DEFAULT        NUM_SERIAL_BAUD_115200
#define SERIAL_STOP_DEFAULT        NUM_SERIAL_STOP_1
#define SERIAL_PARITY_DEFAULT      NUM_SERIAL_PARITY_NONE
#define SERIAL_WORD_LENGTH_DEFAULT NUM_SERIAL_WORD_LENGTH_8

#define DAT_IO_SERIAL_FLOW_CONTROL_DEFAULT_RTSCTS

#ifdef DAT_IO_SERIAL_FLOW_CONTROL_DEFAULT_XONXOFF
#define SERIAL_FLAGS_DEFAULT      (NUM_SERIAL_FLOW_XONXOFF_RX|NUM_SERIAL_FLOW_XONXOFF_TX)
#elif defined(DAT_IO_SERIAL_FLOW_CONTROL_DEFAULT_RTSCTS)
#define SERIAL_FLAGS_DEFAULT      (NUM_SERIAL_FLOW_RTSCTS_RX|NUM_SERIAL_FLOW_RTSCTS_TX)
#elif defined(DAT_IO_SERIAL_FLOW_CONTROL_DEFAULT_DSRDTR)
#define SERIAL_FLAGS_DEFAULT      (NUM_SERIAL_FLOW_DSRDTR_RX|NUM_SERIAL_FLOW_DSRDTR_TX)
#else
#define SERIAL_FLAGS_DEFAULT      0
#endif

typedef enum SerialControl {
    SERIALCONTROL_OPERATIONMASK     = 0xFFFF0000,
    SERIALCONTROL_OBJECTMASK        = 0x0000FFFF,

    SERIALCONTROL_GETCONFIG         = 0x00010000,
    SERIALCONTROL_SETCONFIG         = 0x00020000,
    SERIALCONTROL_WAITEVENT         = 0x00030000
} SerialControl;

#ifdef __cplusplus
}
#endif

#endif // __ELASTOS_SERIALIO_H__
